using UnityEngine;
using System.Collections.Generic;
using System;
using System.Collections;


public class WorldMoveActorBase
{
    private const float MIN_DISTANCE = 0.01f;


    //当前所处的路径点的索引值
    private int mCurTargetIndex;
    private Coroutine mMoveCoroutine;

    //移动对象的唯一id，对玩家来说是武将的card_id，对NPC来说是npc军队的唯一id
    protected uint mActorID;

    //操作的对象
    private Transform mActorTran;
    public Transform ActorTran
    {
        get
        {
            return mActorTran;
        }
    }


    //是否在移动
    private bool mMoving;
    public bool Moving
    {
        get
        {
            return mMoving;
        }
    }


    //城池索引列表，即路径点中是城池点的集合
    private List<int> _cityIndexLst = null;
    private List<int> CityIndexLst
    {
        get
        {
            if (_cityIndexLst == null)
            {
                _cityIndexLst = new List<int>();
            }
            return _cityIndexLst;
        }
    }


    //路径点列表
    private List<Vector3> _path = null;
    private List<Vector3> Path
    {
        get
        {
            if (_path == null)
            {
                _path = new List<Vector3>();
            }
            return _path;
        }
    }


    //路段移动速度列表，每个路段通过时间一致，速度不一致
    private List<float> _moveSpeedLst = null;
    private List<float> MoveSpeedLst
    {
        get
        {
            if (_moveSpeedLst == null)
            {
                _moveSpeedLst = new List<float>();
            }
            return _moveSpeedLst;
        }
    }


    //当前位置
    private Vector3 CurPos
    {
        get
        {
            return mActorTran.position;
        }
        set
        {
            mActorTran.position = value;
        }
    }

    public WorldMoveActorBase(uint actorID)
    {
        mActorID = actorID;
    }

    public void SetActorTran(Transform actor)
    {
        mActorTran = actor;
    }

    public void StopMove()
    {
        Path.Clear();
        CityIndexLst.Clear();
        MoveSpeedLst.Clear();

        mMoving = false;

        //todo
        // GameUtils.StopCoroutine(mMoveCoroutine);
    }

    /// <summary>
    /// 移动接口，传入初始的路径
    /// </summary>
    /// <param name="path"></param>
    public void Move(List<Vector3> path)
    {
        if (mActorTran == null)
        {
            Debug.LogErrorFormat("mActorInfo == null");
            return;
        }
        if (mMoving == true)
        {
            Debug.LogFormat("mActorInfo is Moving");
            return;
        }

        SetPath(path);
        float moveSpeed = GetMoveSpeed();
        if (moveSpeed == 0f)
        {
            return;
        }

        //todo
        // mMoveCoroutine = GameUtils.StartCoroutineSingle(IMove(moveSpeed));
    }

    /// <summary>
    /// 移动的实际逻辑
    /// </summary>
    /// <param name="moveSpeed"></param>
    /// <returns></returns>
    IEnumerator IMove(float moveSpeed)
    {
        mMoving = true;
        NotifyLeaveCity();
        while (mCurTargetIndex < Path.Count)
        {
            CurPos = Vector3.MoveTowards(CurPos, Path[mCurTargetIndex], moveSpeed * Time.deltaTime);
            if (Vector3.Distance(CurPos, Path[mCurTargetIndex]) <= MIN_DISTANCE)
            {
                NotifyEatSpot(mCurTargetIndex);
                if (IsCityIndex(mCurTargetIndex) == true)
                {
                    NotifyArriveCity();

                    if (Path.Count != 0 && mCurTargetIndex != Path.Count - 1)//到达城池点，寻路还没结束，就需要获取下一段的速度了
                    {
                        NotifyLeaveCity();
                        moveSpeed = GetMoveSpeed();

                        if (moveSpeed == 0f)
                        {
                            mMoving = false;
                            yield break;
                        }
                    }
                }
                mCurTargetIndex++;
            }
            yield return null;
        }
        mMoving = false;
    }

    /// <summary>
    /// 获取当前路段移动速度
    /// </summary>
    /// <returns></returns>
    private float GetMoveSpeed()
    {
        if (MoveSpeedLst.Count == 0)
        {
            Debug.LogErrorFormat("No SpeedLst,please @wangzhe");
            return 0f;
        }

        float moveSpeed = MoveSpeedLst[0];
        MoveSpeedLst.RemoveAt(0);

        return moveSpeed;
    }

    /// <summary>
    /// 补充路径，顺带填充城池点和不同路段的速度列表
    /// </summary>
    /// <param name="path"></param>
    public void AddPath(List<Vector3> path)
    {
        this.Path.AddRange(path);

        if (CityIndexLst.Count == 0)
        {
            CityIndexLst.Add(0);
            CityIndexLst.Add(path.Count);
        }
        else
        {
            int lastIndex = CityIndexLst[CityIndexLst.Count - 1];
            CityIndexLst.Add(path.Count + lastIndex);
        }

        path.Insert(0, ActorTran.position);
        float len = GetPathLen(path);
        float time = GetMaxTime();
        float speed = len / time;
        MoveSpeedLst.Add(speed);
    }

    /// <summary>
    /// 设置初始路径
    /// </summary>
    /// <param name="path"></param>
    private void SetPath(List<Vector3> path)
    {
        this.Path.Clear();
        this.Path.AddRange(path);

        CityIndexLst.Clear();
        // CityIndexLst.Add(0);
        CityIndexLst.Add(path.Count - 1);

        path.Insert(0, ActorTran.position);
        float len = GetPathLen(path);
        float time = GetMaxTime();
        float speed = len / time;
        MoveSpeedLst.Clear();
        MoveSpeedLst.Add(speed);

        mCurTargetIndex = 0;
    }

    /// <summary>
    /// 计算路段长度
    /// </summary>
    /// <param name="path"></param>
    /// <returns></returns>
    private float GetPathLen(List<Vector3> path)
    {
        float ret = 0.0f;
        for (int i = 0; i < path.Count; i++)
        {
            if (i != path.Count - 1)
            {
                ret += Vector3.Distance(path[i], path[i + 1]);
            }
        }
        return ret;
    }

    /// <summary>
    /// 获取移动一个路段需要花费的时间 
    /// </summary>
    /// <returns></returns>
    public float GetMaxTime()//todo 优化
    {
        float ret = 1f;
        // ret = BaseDefine.GetFloatVal(BASE_DEFINE.BD_INITIAL_MOVE_SPEED);
        // float ratio = BaseDefine.GetFloatVal(BASE_DEFINE.BD_WAIT_TIME_PRESENT);
        // ret = ret * ratio;

        // EVIPPrivilege e = EVIPPrivilege.WorldMoveSpeed;

        // if (VIPMgr.Instance.CheckPrivilegeActive(e) == true)
        // {
        //     string param = VIPMgr.Instance.GetPrivilegeParam(e);
        //     float paramFloat;
        //     if (float.TryParse(param, out paramFloat))
        //     {
        //         ret = ret * (1 - paramFloat / 100);
        //     }
        // }

        return ret;
    }

    /// <summary>
    /// 在城市上方 散开
    /// </summary>
    public void MoveAOffset(Transform cityTrans, int radius, float rate)
    {
        var deg = 2 * Mathf.PI * rate;
        var worldPos = cityTrans.TransformPoint(new Vector3(Mathf.Cos(deg), 0, Mathf.Sin(deg)) * radius);
        worldPos.y = mActorTran.position.y;
        mActorTran.LookAt(worldPos);
        mActorTran.position = worldPos;
    }


    /// <summary>
    /// 判断是否为城池点
    /// </summary>
    /// <param name="mCurTargetIndex"></param>
    /// <returns></returns>
    private bool IsCityIndex(int mCurTargetIndex)
    {
        return CityIndexLst.Contains(mCurTargetIndex);
    }

    /// <summary>
    /// 通知吃豆豆^_^
    /// </summary>
    /// <param name="index"></param>
    protected virtual void NotifyEatSpot(int index) { }

    /// <summary>
    /// 通知到达城池点
    /// </summary>
    protected virtual void NotifyArriveCity()
    {
        UNotifyCenter.postNotification(UNotifyMsg.Msg_MoveActorArriveCity, mActorID);
        UNotifyCenter.postNotification(UNotifyMsg.Msg_MoveActorArriveCityLate, mActorID);
    }

    /// <summary>
    /// 通知离开城池点
    /// </summary>
    protected virtual void NotifyLeaveCity()
    {
        UNotifyCenter.postNotification(UNotifyMsg.Msg_MoveActorLeaveCity, mActorID);
    }
}

public class WorldMoveArmy : WorldMoveActorBase
{
    public WorldMoveArmy(uint actorID) : base(actorID)
    {

    }

    /// <summary>
    /// 通知吃豆豆^_^
    /// </summary>
    /// <param name="index"></param>
    protected override void NotifyEatSpot(int index)
    {
        UNotifyCenter.postNotification(UNotifyMsg.Msg_MoveActorEatSpot, mActorID, index);
    }
}

public class WorldMoveNPC : WorldMoveActorBase
{
    public WorldMoveNPC(uint actorID) : base(actorID)
    {

    }
}
